#include "Bezier.hpp"


std::vector<double> xCoords, yCoords, xDerivatives, yDerivatives;

// Function to calculate y value for the positive part of the curve
double calculateYPositive(double x) {
    return 2.0/3.0 * (std::sqrt(std::abs(x)) + std::sqrt(3.0 - x * x));
}

// Function to calculate y value for the negative part of the curve
double calculateYNegative(double x) {
    return 2.0/3.0 * (std::sqrt(std::abs(x)) - std::sqrt(3.0 - x * x));
}

// Function to calculate the derivative of y with respect to x
double calculateDerivative(double x, double y) {
    if (x > 0) {
        double sqrtX = std::sqrt(x);
        return 1.0/3.0 * (1/sqrtX - 2 * x / (1.5 * y - sqrtX));
    } else if (x < 0) {
        double sqrtX = std::sqrt(-x);
        return -1.0/3.0 * (1/sqrtX + 2 * x / (1.5 * y - sqrtX));
    }
    return 0;
}

void initializeData(int m) {
    double deltaX = (4.0 * std::sqrt(3.0) - 4e-3) / (m - 2);
    int half = m / 2;
    xCoords.clear();
    yCoords.clear();
    xDerivatives.clear();
    yDerivatives.clear();
    xCoords.reserve(m);
    yCoords.reserve(m);
    xDerivatives.reserve(m);
    yDerivatives.reserve(m);

    for (int i = 0; i < half; ++i) {
        double x = -std::sqrt(3.0) + 1e-3 + i * deltaX;
        xCoords.push_back(x);
        yCoords.push_back(calculateYPositive(x));
        xDerivatives.push_back(deltaX / 20);
        yDerivatives.push_back(calculateDerivative(x, yCoords.back()) * deltaX / 20);
    }
    for (int i = 0; i < half; ++i) {
        double x = std::sqrt(3.0) - 1e-3 - i * deltaX;
        xCoords.push_back(x);
        yCoords.push_back(calculateYNegative(x));
        xDerivatives.push_back(-deltaX / 20);
        yDerivatives.push_back(-calculateDerivative(x, yCoords.back()) * deltaX / 20);
    }
}

int main() {
    std::vector<int> mValues = {10, 40, 160};
    for (int m : mValues) {
        initializeData(m);
        Bezier bezier(xCoords, yCoords, xDerivatives, yDerivatives);
        std::string filename = "./data/2F_" + std::to_string(m) + ".txt";
        std::ofstream outputFile(filename);
        for (double t = 0; t <= static_cast<double>(m); t += 0.01) {
            std::vector<double> point = bezier(t);
            outputFile << point[0] << "," << point[1] << std::endl;
        }
        outputFile.close();
    }
    return 0;
}